/**
 * 
 */
package jvs.peer.net;

import java.io.IOException;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketAddress;
import java.net.SocketException;
import java.nio.channels.ServerSocketChannel;

import jvs.peer.io.Channel;
import jvs.peer.io.ChannelManager;
import jvs.peer.util.Log;

/**
 * @author qiangli
 * 
 */
public class PeerServerSocket extends ServerSocket {
	private ChannelManager man = null;
	
	private int localPort = -1;
	private SocketAddress localSocketAddress;
	private int receiveBufferSize = 1024;
	private int soTimeout = -1;
	private boolean bound = false;
	private boolean closed = false;
	private boolean reuseAddress = false;
	private InetAddress address = null;
	private Channel channel;
	private final String network;
	
	public PeerServerSocket(String network) throws IOException {
		this.network = network;
		this.man = ChannelManager.getInstance(network);
	}

	@Override
	public Socket accept() throws IOException {
		if (Log.DEBUG) {
			Log.log(this, "accepting...");
		}
		channel = man.acceptChannel();
		PeerSocket s = new PeerSocket(network, channel);
		
		if (Log.DEBUG) {
			Log.log(this, "accepted network: " + network +" channel: " + channel);
		}
		
		return s;
	}

	@Override
	public void bind(SocketAddress endpoint, int backlog) throws IOException {
		//
		this.bound = true;
	}

	@Override
	public void bind(SocketAddress endpoint) throws IOException {
		//
		this.bound = true;
	}

	@Override
	public void close() throws IOException {
		if (channel != null) {
			channel.close();
			man.remove(channel);
			channel = null;
		}
	}

	@Override
	public ServerSocketChannel getChannel() {
		throw new RuntimeException("Not supported");
	}

	@Override
	public InetAddress getInetAddress() {
		return address;
	}

	@Override
	public int getLocalPort() {
		return localPort;
	}

	@Override
	public SocketAddress getLocalSocketAddress() {
		return localSocketAddress;
	}

	@Override
	public synchronized int getReceiveBufferSize() throws SocketException {

		return receiveBufferSize;
	}

	@Override
	public boolean getReuseAddress() throws SocketException {
		return reuseAddress;
	}

	@Override
	public synchronized int getSoTimeout() throws IOException {
		return soTimeout;
	}

	@Override
	public boolean isBound() {
		return bound;
	}

	@Override
	public boolean isClosed() {
		return closed;
	}

	@Override
	public void setPerformancePreferences(int connectionTime, int latency,
			int bandwidth) {
		//
	}

	@Override
	public synchronized void setReceiveBufferSize(int size)
			throws SocketException {
		this.receiveBufferSize = size;
	}

	@Override
	public void setReuseAddress(boolean on) throws SocketException {
		this.reuseAddress = on;
	}

	@Override
	public synchronized void setSoTimeout(int timeout) throws SocketException {
		this.soTimeout = timeout;
	}

	public String getNetwork() {
		return network;
	}

	@Override
	public String toString() {
		return "PeerServerSocket [localPort=" + localPort
				+ ", localSocketAddress=" + localSocketAddress
				+ ", receiveBufferSize=" + receiveBufferSize + ", soTimeout="
				+ soTimeout + ", bound=" + bound + ", closed=" + closed
				+ ", reuseAddress=" + reuseAddress + ", address=" + address
				+ ", channel=" + channel + ", network=" + network + "]";
	}

}
